/*
   Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
   Ported to Arduino ESP32 by Evandro Copercini
   Changed to a beacon scanner to report iBeacon, EddystoneURL and EddystoneTLM beacons by beegee-tokyo
*/

#include <Arduino.h>

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <BLEEddystoneURL.h>
#include <BLEBeacon.h>

#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8))

int scanTime = 5; //In seconds
BLEScan *pBLEScan;

class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
{
    void onResult(BLEAdvertisedDevice advertisedDevice)
    {
      if (advertisedDevice.haveName())
      {
        Serial.print("Device name: ");
        Serial.println(advertisedDevice.getName().c_str());
        Serial.println("");
      }

      if (advertisedDevice.haveServiceUUID()) {
        BLEUUID devUUID = advertisedDevice.getServiceUUID();
        Serial.print("Found ServiceUUID: ");
        Serial.println(devUUID.toString().c_str());
        Serial.println("");

        Serial.print("payLoad: ");
        uint8_t *payLoad = advertisedDevice.getPayload();

        BLEUUID checkUrlUUID = (uint16_t)0xfeaa;
   
        if (advertisedDevice.getServiceUUID().equals(checkUrlUUID)) {
          if (payLoad[11] == 0x10) {
            Serial.println("Found an EddystoneURL beacon!");
            BLEEddystoneURL foundEddyURL = BLEEddystoneURL();
            std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct!

            foundEddyURL.setData(eddyContent);
            std::string bareURL = foundEddyURL.getURL();
            size_t payLoadLen = advertisedDevice.getPayloadLength();
            Serial.printf("payLoadLen %d\n", payLoadLen);
//          if (bareURL[0] == 0x00) {
//            size_t payLoadLen = advertisedDevice.getPayloadLength();
//            Serial.println("DATA-->");
//            for (int idx = 0; idx < payLoadLen; idx++)
//            {
//              Serial.printf("0x%08X ", payLoad[idx]);
//            }
//            Serial.println("\nInvalid Data");
//            return;
//          }

            Serial.printf("Found URL: %s\n", foundEddyURL.getURL().c_str());
            Serial.printf("Decoded URL: %s\n", foundEddyURL.getDecodedURL().c_str());
            Serial.printf("TX power %d\n", foundEddyURL.getPower());
            Serial.println("\n");
           }
        }
      }
    }
};

void setup()
{
  Serial.begin(115200);
  Serial.println("Scanning...");
  // 初始化BLE设备环境
  BLEDevice::init("");
  // 获取扫描对象入口
  pBLEScan = BLEDevice::getScan(); //create new scan
  // 设置扫描回调
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  // 设置主动扫描
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99); // less or equal setInterval value
}

void loop(){
  // put your main code here, to run repeatedly:
  BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
  Serial.print("Devices found: ");
  Serial.println(foundDevices.getCount());
  Serial.println("Scan done!");
  pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory
  delay(1000);
}
